class EU4EncoderDecoder:
    def __init__(self):
        # 定义 cp1252 到 UTF - 8 的映射
        self.cp1252_to_utf8_map = {
            0x80: 0x20AC, 0x82: 0x201A, 0x83: 0x0192, 0x84: 0x201E,
            0x85: 0x2026, 0x86: 0x2020, 0x87: 0x2021, 0x88: 0x02C6,
            0x89: 0x2030, 0x8A: 0x0160, 0x8B: 0x2039, 0x8C: 0x0152,
            0x8E: 0x017D, 0x91: 0x2018, 0x92: 0x2019, 0x93: 0x201C,
            0x94: 0x201D, 0x95: 0x2022, 0x96: 0x2013, 0x97: 0x2014,
            0x98: 0x02DC, 0x99: 0x2122, 0x9A: 0x0161, 0x9B: 0x203A,
            0x9C: 0x0153, 0x9E: 0x017E, 0x9F: 0x0178
        }
        # 定义 UTF - 8 到 cp1252 的逆向映射
        self.utf8_to_cp1252_map = {v: k for k, v in self.cp1252_to_utf8_map.items()}

    def cp1252_to_utf8(self, char):
        return self.cp1252_to_utf8_map.get(char, char)

    def utf8_to_cp1252(self, char):
        return self.utf8_to_cp1252_map.get(char, char)

    def encode_char(self, char, to_utf8=True, new_version=True):
        code_point = ord(char)
        if code_point < 256:
            return char
        hex_code = format(code_point, 'x').zfill(4)
        low = int(hex_code[-2:], 16)
        high = int(hex_code[:2], 16)

        low_byte_offset = 14 if new_version else 15
        high_byte_offset = -9

        internal_chars = [
            0x00, 0x0A, 0x0D,
            0x20,
            0x22, 0x24,
            0x40, 0x5B, 0x5C,
            0x7B, 0x7D, 0x7E, 0x80,
            0xA3, 0xA4, 0xA7, 0xBD,
            0x3B,
            0x5D,
            0x5F,
            0x3D,
            0x23
        ]

        if to_utf8:
            internal_chars.append(0x2F)
            if not new_version:
                internal_chars.remove(0x20)

        escape_chr = 0x10
        if high in internal_chars:
            escape_chr += 2
        if low in internal_chars:
            escape_chr += 1

        if escape_chr == 0x11:
            low += low_byte_offset
        elif escape_chr == 0x12:
            high += high_byte_offset
        elif escape_chr == 0x13:
            low += low_byte_offset
            high += high_byte_offset

        if to_utf8:
            low = self.cp1252_to_utf8(low)
            high = self.cp1252_to_utf8(high)

        return ''.join(chr(c) for c in [escape_chr, low, high])

    def decode_char(self, encoded_char, to_utf8=True, new_version=True):
        if len(encoded_char) == 1:
            return encoded_char
        escape_chr, low, high = [ord(c) for c in encoded_char]

        if to_utf8:
            low = self.utf8_to_cp1252(low)
            high = self.utf8_to_cp1252(high)

        low_byte_offset = 14 if new_version else 15
        high_byte_offset = -9

        if escape_chr == 0x11:
            low -= low_byte_offset
        elif escape_chr == 0x12:
            high -= high_byte_offset
        elif escape_chr == 0x13:
            low -= low_byte_offset
            high -= high_byte_offset

        hex_code = f"{high:02x}{low:02x}"
        code_point = int(hex_code, 16)
        return chr(code_point)

    def encode_string(self, s, to_utf8=True, new_version=True):
        encoded = ""
        for char in s:
            encoded += self.encode_char(char, to_utf8, new_version)
        return encoded

    def decode_string(self, encoded_str, to_utf8=True, new_version=True):
        decoded = ""
        i = 0
        while i < len(encoded_str):
            char = encoded_str[i]
            if 32 <= ord(char) <= 126:
                # 如果是英文字母、$或空格，直接添加到解码结果中
                decoded += char
                i += 1
            elif ord(char) < 0x10:
                decoded += char
                i += 1
            else:
                encoded_char = encoded_str[i:i + 3]
                decoded += self.decode_char(encoded_char, to_utf8, new_version)
                i += 3
        return decoded

    def encode(self, s):
        return self.encode_string(s)

    def decode(self, s):
        return self.decode_string(s)



class EU4EncoderDecoderTest:

    def test_encode(self):
        print("加密测试")
        encoder_decoder = EU4EncoderDecoder()
        originString = "留任 $MONARCH$"
        encodeString = encoder_decoder.encode(originString)
        decodeString = encoder_decoder.decode(encodeString)
        print(f"Original: {originString}, Encoded: {encodeString}, Decoded: {decodeString}")


    def test_decode(self):
        print("解密测试")
        encoder_decoder = EU4EncoderDecoder()
        encodeString = "$MONARCHTITLE$ $MONARCH$«ˆNg³R"
        decodeString = encoder_decoder.decode(encodeString)
        print(decodeString)


if __name__ == "__main__":
    EU4EncoderDecoderTest().test_encode()
    EU4EncoderDecoderTest().test_decode()
